<template>
  <div class="workflow-canvas-container">
    <div 
      ref="canvasRef"
      class="workflow-canvas"
      @click="clearSelection"
      @dragover="handleDragOver"
      @drop="handleDrop"
      @mouseup="handleMouseUp"
      @mousemove="handleMouseMove"
      @mousedown="handleCanvasMouseDown"
      @contextmenu.prevent="handleContextMenu"
      :class="{ 'grabbing': isDraggingCanvas }"
    >
      <div class="canvas-header">
        <h2>数据节点工作流</h2>
      </div>
      <div class="canvas-content">
        <!-- 这里将放置节点和连接 -->
        <div class="placeholder-message" v-if="!workflowStore.currentWorkflow">
          <p>请创建或选择一个工作流</p>
          <el-button type="primary" @click="workflowStore.createWorkflow('新工作流')">
            创建新工作流
          </el-button>
        </div>

        <!-- 添加系统节点按钮 -->
        <div class="canvas-toolbar">
          <el-button
            type="primary"
            size="small"
            @click="initializeSystemNodes"
          >
            初始化系统节点
          </el-button>

          <el-button-group class="scale-controls">
            <el-button size="small" @click="canvasScale *= 1.1">
              <el-icon><ZoomIn /></el-icon>
              放大
            </el-button>
            <el-button size="small" @click="canvasScale = 1">
              <el-icon><Position /></el-icon>
              还原
            </el-button>
            <el-button size="small" @click="canvasScale *= 0.9">
              <el-icon><ZoomOut /></el-icon>
              缩小
            </el-button>
          </el-button-group>
        </div>

        <!-- 渲染节点和连接 -->
        <div
          v-if="currentWorkflow"
          class="canvas-transform-layer"
          :style="{
            transform: `scale(${canvasScale}) translate(${viewPosition.x}px, ${viewPosition.y}px)`
          }"
        >
          <!-- 连接层 -->
          <svg class="connections-layer">
            <!-- 已有连接 -->
            <WorkflowConnection
              v-for="connection in currentWorkflow.connections"
              :key="connection.id"
              :connection="connection"
              :nodes="currentWorkflow.nodes"
            />
          </svg>

          <!-- 节点层 -->
          <WorkflowNode
            v-for="node in currentWorkflow.nodes"
            :key="node.id"
            :node="node"
            :isConnectionHovering="connectionHoveringNodeId === node.id"
            @move="handleNodeMove"
            @start-connection="handleStartConnection"
          />
        </div>

        <!-- 临时连接线 -->
        <svg
          v-if="isCreatingConnection"
          class="temp-connections-layer"
          :style="{
            transform: `scale(${canvasScale}) translate(${viewPosition.x}px, ${viewPosition.y}px)`
          }"
        >
          <defs>
            <marker
              id="temp-arrowhead"
              viewBox="0 0 10 10"
              refX="8"
              refY="5"
              markerWidth="6"
              markerHeight="6"
              orient="auto"
            >
              <path d="M 0 0 L 10 5 L 0 10 z" fill="#409EFF" />
            </marker>
          </defs>
          <path
            :d="getTemporaryConnectionPath()"
            stroke="#409EFF"
            stroke-width="2"
            fill="none"
            stroke-dasharray="5,5"
            marker-end="url(#temp-arrowhead)"
          />
        </svg>
      </div>
    </div>

    <!-- 右键菜单 -->
    <div
      v-if="showContextMenu"
      class="canvas-context-menu"
      :style="{ left: contextMenuPosition.x + 'px', top: contextMenuPosition.y + 'px' }"
    >
      <div class="menu-section">
        <div class="menu-title">添加节点</div>
        <div class="menu-items">
          <div
            v-for="category in nodeCategories"
            :key="category.name"
            class="menu-category"
          >
            <div class="category-title">{{ category.name }}</div>
            <div
              v-for="node in category.nodes"
              :key="node.type"
              class="menu-item"
              @click="addNodeFromMenu(node.type, node.label)"
            >
              <el-icon v-if="node.icon"><component :is="node.icon" /></el-icon>
              <span>{{ node.label }}</span>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 添加节点属性面板 -->
    <node-config-panel
      v-if="workflowStore.selectedNodeId"
      :node="selectedNode"
    />
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from 'vue'
import { useWorkflowStore } from '@/store/workflow'
import WorkflowNode from './WorkflowNode.vue'
import WorkflowConnection from './WorkflowConnection.vue'
import NodeConfigPanel from './NodeConfigPanel.vue'
import { ZoomIn, ZoomOut, Position } from '@element-plus/icons-vue'
import { nodeTypes } from '@/config/nodeTypes'

const workflowStore = useWorkflowStore()
const canvasRef = ref(null)

// 计算当前工作流
const currentWorkflow = computed(() => workflowStore.currentWorkflow)

// 计算当前选中的节点
const selectedNode = computed(() => {
  if (!workflowStore.selectedNodeId || !workflowStore.currentWorkflow) return null
  return workflowStore.currentWorkflow.nodes.find(
    node => node.id === workflowStore.selectedNodeId
  )
})

// 画布缩放与平移
const canvasScale = ref(1)
const viewPosition = ref({ x: 0, y: 0 })

// 拖拽相关
function handleDragOver(event: DragEvent) {
  event.preventDefault()
}
function handleDrop(event: DragEvent) {
  event.preventDefault()
  if (!currentWorkflow.value) return
  const nodeType = event.dataTransfer?.getData('application/node-type')
  const nodeLabel = event.dataTransfer?.getData('application/node-label')
  if (nodeType && nodeLabel) {
    // 计算相对于画布的坐标
    const rect = (event.currentTarget as HTMLElement).getBoundingClientRect()
    const x = (event.clientX - rect.left - viewPosition.value.x) / canvasScale.value
    const y = (event.clientY - rect.top - viewPosition.value.y) / canvasScale.value
    workflowStore.addNode(nodeType, nodeLabel, x, y)
  }
}

// 初始化系统节点
function initializeSystemNodes() {
  if (!currentWorkflow.value) return
  // 只添加一次
  if (currentWorkflow.value.nodes.length === 0) {
    workflowStore.addNode('start', '开始', 100, 200)
    workflowStore.addNode('end', '结束', 500, 200)
  }
}

// 节点移动
function handleNodeMove(nodeId: string, x: number, y: number) {
  // 确保坐标是有效的数字
  if (isNaN(x) || isNaN(y)) return;

  // 直接更新节点位置，不进行坐标转换
  // 因为在 WorkflowNode.vue 中已经考虑了当前位置
  workflowStore.updateNodePosition(nodeId, {
    x: Math.round(x),
    y: Math.round(y)
  });
}

// 连接相关（如有需要可补充）

// 清除选择
function clearSelection(event) {
  // 确保点击的是画布本身，而不是节点或其他元素
  if (event.target === event.currentTarget ||
      event.target.classList.contains('canvas-content')) {
    workflowStore.clearSelection();
  }
}

// 连接创建相关状态
const isCreatingConnection = ref(false)
const connectionSource = ref({
  nodeId: '',
  portId: '',
  isInput: false,
  x: 0,
  y: 0
})
const mousePosition = ref({ x: 0, y: 0 })

// 处理开始创建连接
function handleStartConnection(nodeId: string, portId: string, isInput: boolean, event: MouseEvent) {
  isCreatingConnection.value = true

  // 获取源节点和端口信息
  const sourceNode = currentWorkflow.value?.nodes.find(node => node.id === nodeId)
  if (!sourceNode) return

  // 计算连接起点坐标
  const portIndex = isInput
    ? sourceNode.inputs.findIndex(port => port.id === portId)
    : sourceNode.outputs.findIndex(port => port.id === portId)

  // 锚点在边框上的位置
  const x = isInput
    ? sourceNode.position.x // 左侧锚点，直接使用节点左边界
    : sourceNode.position.x + 180 // 修正为节点宽度

  const y = sourceNode.position.y + 40 + (portIndex * 30) + 15 // 锚点垂直位置，加15使其垂直居中

  // 保存连接源信息
  connectionSource.value = {
    nodeId,
    portId,
    isInput,
    x,
    y
  }

  // 初始化鼠标位置 - 使用画布坐标系
  const rect = canvasRef.value.getBoundingClientRect()
  mousePosition.value = {
    x: (event.clientX - rect.left - viewPosition.value.x) / canvasScale.value,
    y: (event.clientY - rect.top - viewPosition.value.y) / canvasScale.value
  }

  // 添加事件监听
  document.addEventListener('mouseup', handleMouseUp)
  document.addEventListener('mousemove', handleMouseMove)
}

// 连接悬停相关
const connectionHoveringNodeId = ref(null)

// 处理鼠标移动
function handleMouseMove(event: MouseEvent) {
  // 如果正在拖动画布，不处理连接线逻辑
  if (isDraggingCanvas.value) return
  
  if (!isCreatingConnection.value) return
  
  // 更新鼠标位置 - 直接使用相对于画布的坐标，不需要再减去viewPosition
  const rect = canvasRef.value.getBoundingClientRect()
  mousePosition.value = {
    x: (event.clientX - rect.left) / canvasScale.value,
    y: (event.clientY - rect.top) / canvasScale.value
  }
  
  // 检测连接线是否接触到节点
  checkConnectionNodeHover(event)
}

// 检测连接线是否接触到节点
function checkConnectionNodeHover(event: MouseEvent) {
  // 获取鼠标下方的元素
  const element = document.elementFromPoint(event.clientX, event.clientY)

  // 检查是否是节点元素
  const nodeElement = element?.closest('.workflow-node')
  if (nodeElement) {
    const nodeId = nodeElement.getAttribute('data-node-id')

    // 确保不是连接源节点
    if (nodeId && nodeId !== connectionSource.value.nodeId) {
      connectionHoveringNodeId.value = nodeId
      return
    }
  }

  // 如果不是节点元素，清除悬停状态
  connectionHoveringNodeId.value = null
}

// 处理鼠标释放
function handleMouseUp(event: MouseEvent) {
  if (!isCreatingConnection.value) return;

  // 检查是否释放在锚点上
  const element = document.elementFromPoint(event.clientX, event.clientY);
  const anchorElement = element?.closest('.anchor-point');

  if (anchorElement) {
    const nodeId = anchorElement.getAttribute('data-node-id');
    const portId = anchorElement.getAttribute('data-port-id');
    const isInput = anchorElement.closest('.left-anchors') !== null;

    // 确保不是同一个端口
    if (nodeId && portId &&
        (nodeId !== connectionSource.value.nodeId ||
         portId !== connectionSource.value.portId)) {

      // 确保一个是输入端口，一个是输出端口
      if (isInput !== connectionSource.value.isInput) {
        // 确定源和目标
        let sourceNodeId, sourcePortId, targetNodeId, targetPortId;

        if (connectionSource.value.isInput) {
          // 当前源是输入端口，目标是输出端口
          targetNodeId = connectionSource.value.nodeId;
          targetPortId = connectionSource.value.portId;
          sourceNodeId = nodeId;
          sourcePortId = portId;
        } else {
          // 当前源是输出端口，目标是输入端口
          sourceNodeId = connectionSource.value.nodeId;
          sourcePortId = connectionSource.value.portId;
          targetNodeId = nodeId;
          targetPortId = portId;
        }

        // 创建连接
        workflowStore.addConnection(sourceNodeId, sourcePortId, targetNodeId, targetPortId);
      }
    }
  } else if (connectionHoveringNodeId.value) {
    // 如果释放在节点上但不是锚点，尝试找到合适的端口自动连接
    tryAutoConnect(connectionHoveringNodeId.value);
  }

  // 重置连接创建状态
  isCreatingConnection.value = false;
  connectionHoveringNodeId.value = null;

  // 移除事件监听
  document.removeEventListener('mouseup', handleMouseUp);
  document.removeEventListener('mousemove', handleMouseMove);
}

// 尝试自动连接到合适的端口
function tryAutoConnect(targetNodeId: string) {
  if (!currentWorkflow.value) return;

  const sourceNode = currentWorkflow.value.nodes.find(
    node => node.id === connectionSource.value.nodeId
  );

  const targetNode = currentWorkflow.value.nodes.find(
    node => node.id === targetNodeId
  );

  if (!sourceNode || !targetNode) return;

  // 根据连接源是输入还是输出端口，选择目标节点的合适端口
  if (connectionSource.value.isInput) {
    // 源是输入端口，需要找目标节点的输出端口
    if (targetNode.outputs && targetNode.outputs.length > 0) {
      // 简单起见，选择第一个输出端口
      const targetPortId = targetNode.outputs[0].id;

      workflowStore.addConnection(
        targetNodeId,
        targetPortId,
        connectionSource.value.nodeId,
        connectionSource.value.portId
      );
    }
  } else {
    // 源是输出端口，需要找目标节点的输入端口
    if (targetNode.inputs && targetNode.inputs.length > 0) {
      // 简单起见，选择第一个输入端口
      const targetPortId = targetNode.inputs[0].id;

      workflowStore.addConnection(
        connectionSource.value.nodeId,
        connectionSource.value.portId,
        targetNodeId,
        targetPortId
      );
    }
  }
}

// 计算临时连接路径
function getTemporaryConnectionPath() {
  if (!isCreatingConnection.value) return '';

  const sourceX = connectionSource.value.x;
  const sourceY = connectionSource.value.y;

  // 获取鼠标在画布坐标系中的位置
  const targetX = mousePosition.value.x;
  const targetY = mousePosition.value.y;

  // 计算控制点
  const dx = Math.abs(targetX - sourceX);
  const controlPointOffset = Math.min(150, dx * 0.7);

  // 生成贝塞尔曲线路径
  return connectionSource.value.isInput
    ? `M ${targetX} ${targetY} C ${targetX - controlPointOffset} ${targetY}, ${sourceX + controlPointOffset} ${sourceY}, ${sourceX} ${sourceY}`
    : `M ${sourceX} ${sourceY} C ${sourceX + controlPointOffset} ${sourceY}, ${targetX - controlPointOffset} ${targetY}, ${targetX} ${targetY}`;
}

// 组件挂载时初始化
onMounted(() => {
  // 如果没有当前工作流，创建一个
  if (!workflowStore.currentWorkflow) {
    workflowStore.createWorkflow('新工作流')
    initializeSystemNodes()
  }
})

// 右键菜单相关
const showContextMenu = ref(false)
const contextMenuPosition = ref({ x: 0, y: 0 })

// 处理右键菜单
// 处理右键菜单
function handleContextMenu(event) {
  event.preventDefault();

  // 检查点击是否在节点上
  const nodeElement = event.target.closest('.workflow-node');
  if (nodeElement) {
    // 如果在节点上点击，不显示画布右键菜单
    return;
  }

  // 计算相对于画布的坐标
  const rect = canvasRef.value?.getBoundingClientRect();
  if (!rect) return; // 确保DOM元素存在

  const x = event.clientX - rect.left;
  const y = event.clientY - rect.top;

  // 设置菜单位置
  contextMenuPosition.value = { x, y };
  showContextMenu.value = true;

  // 添加点击外部关闭菜单的事件
  setTimeout(() => {
    // 确保组件仍然挂载
    if (canvasRef.value) {
      document.addEventListener('click', closeContextMenu);
    }
  }, 0);
}

// 关闭菜单函数
function closeContextMenu() {
  // Check if component is still mounted before proceeding
  if (!showContextMenu.value) return;

  showContextMenu.value = false;
  contextMenuPosition.value = { x: 0, y: 0 };

  // Remove event listener
  document.removeEventListener('click', closeContextMenu);
}

// 从菜单添加节点
function addNodeFromMenu(nodeType, nodeLabel) {
  if (!currentWorkflow.value) return

  // 计算相对于画布的坐标
  const rect = canvasRef.value.getBoundingClientRect()
  const x = (contextMenuPosition.value.x - viewPosition.value.x) / canvasScale.value
  const y = (contextMenuPosition.value.y - viewPosition.value.y) / canvasScale.value

  workflowStore.addNode(nodeType, nodeLabel, x, y)
  closeContextMenu()
}

// 组件卸载时清理事件监听
onUnmounted(() => {
  document.removeEventListener('click', closeContextMenu)
  document.removeEventListener('mousemove', handleCanvasDrag)
  document.removeEventListener('mouseup', stopCanvasDrag)
})

// 节点分类
const nodeCategories = computed(() => {
  const categories = []

  Object.entries(nodeTypes).forEach(([type, config]) => {
    const category = config.category || '其他'
    let categoryObj = categories.find(c => c.name === category)

    if (!categoryObj) {
      categoryObj = {
        name: category,
        nodes: []
      }
      categories.push(categoryObj)
    }

    categoryObj.nodes.push({
      type,
      label: config.label,
      icon: config.icon,
      color: config.color
    })
  })

  return categories
})

// 添加辅助线相关状态
const guideLines = ref([]);

// 更新辅助线
function updateGuideLines(lines) {
  guideLines.value = lines;
}

// 添加画布拖动相关状态
const isDraggingCanvas = ref(false)
const lastMousePosition = ref({ x: 0, y: 0 })

// 处理画布鼠标按下事件
function handleCanvasMouseDown(event) {
  // 确保点击的是画布本身，而不是节点或其他元素
  // 检查是否点击在节点、按钮或其他交互元素上
  const isNode = event.target.closest('.workflow-node');
  const isButton = event.target.closest('button');
  const isAnchor = event.target.closest('.anchor-point');
  
  if (!isNode && !isButton && !isAnchor) {
    // 只响应鼠标左键
    if (event.button === 0) {
      event.preventDefault(); // 阻止默认行为
      isDraggingCanvas.value = true;
      lastMousePosition.value = { x: event.clientX, y: event.clientY };
      
      // 添加全局事件监听
      document.addEventListener('mousemove', handleCanvasDrag);
      document.addEventListener('mouseup', stopCanvasDrag);
      
      // 修改鼠标样式
      document.body.style.cursor = 'grabbing';
    }
  }
}

// 处理画布拖动
function handleCanvasDrag(event) {
  if (!isDraggingCanvas.value) return
  
  // 计算鼠标移动距离
  const dx = event.clientX - lastMousePosition.value.x
  const dy = event.clientY - lastMousePosition.value.y
  
  // 更新画布位置
  viewPosition.value = {
    x: viewPosition.value.x + dx,
    y: viewPosition.value.y + dy
  }
  
  // 更新最后鼠标位置
  lastMousePosition.value = { x: event.clientX, y: event.clientY }
}

// 停止画布拖动
function stopCanvasDrag() {
  if (!isDraggingCanvas.value) return
  
  isDraggingCanvas.value = false
  
  // 恢复鼠标样式
  document.body.style.cursor = ''
  
  // 移除全局事件监听
  document.removeEventListener('mousemove', handleCanvasDrag)
  document.removeEventListener('mouseup', stopCanvasDrag)
}
</script>

<style scoped>
.workflow-canvas-container {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.workflow-canvas {
  width: 100%;
  height: 100%;
  background-color: #f5f7fa;
  background-image:
    linear-gradient(rgba(0, 0, 0, 0.1) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 0, 0, 0.1) 1px, transparent 1px);
  background-size: 20px 20px;
  position: relative;
  overflow: hidden;
}

.canvas-header {
  padding: 10px;
  background-color: white;
  border-bottom: 1px solid #dcdfe6;
}

.canvas-content {
  position: relative;
  height: calc(100% - 50px);
  overflow: hidden;
}

.canvas-toolbar {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 100;
  display: flex;
  gap: 10px;
}

.placeholder-message {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  text-align: center;
}

.canvas-transform-layer {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  transform-origin: 0 0;
}

.connections-layer {
  position: absolute;
  width: 100%;
  height: 100%;
  pointer-events: all; /* 修改为 all，使连接线可以接收点击事件 */
}

.temp-connections-layer {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* 右键菜单样式 */
.canvas-context-menu {
  position: absolute;
  background-color: white;
  border: 1px solid #dcdfe6;
  border-radius: 6px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  z-index: 1000;
  min-width: 200px;
  max-height: 80vh;
  overflow-y: auto;
}

.menu-section {
  padding: 8px 0;
}

.menu-title {
  padding: 5px 16px;
  font-weight: bold;
  color: #606266;
  font-size: 14px;
  border-bottom: 1px solid #ebeef5;
}

.menu-items {
  padding: 5px 0;
}

.menu-category {
  margin-bottom: 8px;
}

.category-title {
  padding: 3px 16px;
  font-size: 13px;
  color: #909399;
}

.menu-item {
  padding: 7px 16px;
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  transition: background-color 0.2s;
}

.menu-item:hover {
  background-color: #f5f7fa;
}

.menu-item .el-icon {
  font-size: 16px;
}

/* 辅助线样式 */
.guide-lines-container {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 100;
}

.guide-line {
  stroke-width: 1;
  stroke-dasharray: 5, 5;
}

.guide-line.vertical {
  stroke: #409EFF;
}

.guide-line.horizontal {
  stroke: #67C23A;
}

/* 添加画布拖动相关样式 */
.workflow-canvas {
  cursor: default;
}

.workflow-canvas:hover {
  cursor: grab;
}

.workflow-canvas.grabbing {
  cursor: grabbing !important;
}

/* 当鼠标悬停在画布上时显示可抓取的指针 */
.workflow-canvas:not(.grabbing):hover {
  cursor: grab;
}
</style>